package org.jeecgframework.web.service.impl;

import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.jeecgframework.core.common.service.impl.CommonServiceImpl;
import org.jeecgframework.core.constant.DataBaseConstant;
import org.jeecgframework.core.util.DataUtils;
import org.jeecgframework.core.util.ResourceUtil;
import org.jeecgframework.core.util.StringUtil;
import org.jeecgframework.core.util.oConvertUtils;
import org.jeecgframework.web.cgform.service.build.DataBaseService;
import org.jeecgframework.web.service.ZyWorkFlowService;
import org.jeecgframework.web.system.pojo.base.TSBaseUser;
import org.jeecgframework.web.system.pojo.base.TSUser;
import org.jeecgframework.web.system.service.SystemService;
import org.jeecgframework.workflow.common.WorkFlowGlobals;
import org.jeecgframework.workflow.dao.ActivitiDao;
import org.jeecgframework.workflow.pojo.activiti.ActHiTaskinst;
import org.jeecgframework.workflow.pojo.base.TSBusConfig;
import org.jeecgframework.workflow.service.ActivitiService;
import org.jeecgframework.workflow.service.impl.TaskJeecgService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service("zyWorkFlowService")
@Transactional
public class ZyWorkFlowServiceImpl extends CommonServiceImpl implements ZyWorkFlowService {

    @Autowired
    private ActivitiService activitiService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private SystemService systemService;
    @Autowired
    private DataBaseService dataBaseService;
    @Autowired
    private ActivitiDao activitiDao;
    @Autowired
    private TaskJeecgService taskJeecgService;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private HistoryService historyService;
    @Autowired
    private RepositoryService repositoryService;

    @Override
    public ProcessInstance startOnlineProcess(String tableName, String id, Map<String, Object> paramsMap) {
        StringBuffer sqlBuffer = new StringBuffer ();
        sqlBuffer.append ( "select * from " ).append ( tableName );
        sqlBuffer.append ( " where id='" ).append ( id ).append ( "'" );
        Map<String, Object> dataForm = systemService.findOneForJdbc ( sqlBuffer.toString () );

        dataForm.put ( WorkFlowGlobals.BPM_FORM_CONTENT_URL, "cgFormBuildController.do?ftlForm&tableName=" + tableName + "&mode=read&load=detail&id=" + id );
        dataForm.put ( WorkFlowGlobals.BPM_FORM_KEY, tableName );
        String create_by = dataForm.get ( DataBaseConstant.CREATE_BY_DB ).toString ();//业务数据创建人
        String data_id = id;//online数据ID
        //获取onlinecoding表名
        TSBusConfig tsBusbase = systemService.findUniqueByProperty ( TSBusConfig.class, "onlineId", tableName );
        //1.加载出onlinecoding的表单数据（单表或主表）
        //2.制定表单访问变量content_url,默认等于表单的查看页面
        //3.通过onlinecoding表名,读取流程表单配置,获取流程实例
        paramsMap.putAll ( dataForm );
        ProcessInstance processInstance = activitiService.startOnlineWorkflow ( create_by, data_id, paramsMap, tsBusbase );
        //4.修改onlinecoding表单的BPM业务流程状态
        //dataForm.put(WorkFlowGlobals.BPM_STATUS, WorkFlowGlobals.BPM_BUS_STATUS_2);
        //dataBaseService.updateTable(tableName, id, dataForm);
        //----------------------------------------------------------------
        //5.往原来的流程设计里面设置数据
        Map<String, Object> mp = new HashMap<String, Object> ();
        mp.put ( "id", id );
        mp.put ( "userid", dataForm.get ( DataBaseConstant.CREATE_BY_DB ) );
        mp.put ( "prjstateid", 2 );
        mp.put ( "busconfigid", tsBusbase.getId () );
        activitiDao.insert ( mp );
        return processInstance;
    }

    /**
     * @param veId             业务 主键 ID
     * @param processId
     * @param currentTaskDefId 当前节点定义key
     * @param nextTaskDefId    需要跳转节点定义key
     * @author xiul
     * 2016-03-28
     * Description 工作流-节点跳转
     */
    public void goProcessNode(String veId, String processId,
                              String currentTaskDefId, String nextTaskDefId) {
        //查看最新版本的流程ID
        System.out.println ( "select * from act_re_procdef where KEY_ = '" + processId + "' ORDER BY VERSION_ DESC limit 0,1" );
        Map<String, Object> procDefMap =
                activitiService.findOneForJdbc ( "select * from act_re_procdef where KEY_ = '" + processId + "' ORDER BY VERSION_ DESC limit 0,1" );
        String processDefId = (String) procDefMap.get ( "ID_" );
        List<Map<String, Object>> processInstanceList = activitiService.findForJdbc ( "select * from act_hi_procinst where BUSINESS_KEY_ = ?", veId );
        if (processInstanceList.size () > 0) {
            //去act_ru_task查最新的ID_，（之前驳回之后查出来的list 不正确）
            List<Map<String, Object>> list = activitiService.findForJdbc ( "select * from act_ru_task where PROC_INST_ID_ ='" + processInstanceList.get ( 0 ).get ( "ID_" ) + "' and PROC_DEF_ID_ = '" + processDefId + "' and TASK_DEF_KEY_='" + currentTaskDefId + "'" );
            /*List<Map<String,Object>> list = activitiService.findForJdbc("select * from act_hi_taskinst where PROC_DEF_ID_ = '"+processDefId+"' AND TASK_DEF_KEY_ = '"+currentTaskDefId+"' AND PROC_INST_ID_ = '"+processInstanceList.get(0).get("ID_")+"'");*/
            if (list.size () > 0) {
                String taskId = list.get ( 0 ).get ( "ID_" ).toString ();
                //流程变量参数
                //初始节点签收
                TSUser user = ResourceUtil.getSessionUserName ();
                taskService.claim ( taskId, user.getUserName () );
                Map<String, Object> map = new HashMap<String, Object> ();
                taskJeecgService.goProcessTaskNode ( taskId, nextTaskDefId, map );
            }
        }
    }


    @Override
    public Map<String, Object> processComplete(String model, String processInstanceId, String nextUser, String approvalFlag, String expression) {
        Map<String, Object> returnMap = new HashMap<String, Object> ();
        try {
            Task task = taskService.createTaskQuery ().processInstanceId ( processInstanceId ).active ().singleResult ();
            returnMap.put ( "task", task );
            String taskId = task.getId ();
            if (null != task.getAssignee () && !task.getAssignee ().equals ( "" )) {
                /**
                 * upadte by xiu 因为webservice 请求没有session 所以取不到当前用户，所以这里改为取task历史中的 最后一个 unfinished 的记录的assign
                 * */
                HistoricTaskInstance hisTask = historyService.createHistoricTaskInstanceQuery ().processInstanceId ( processInstanceId ).unfinished ().singleResult ();
                TSBaseUser tsUser = systemService.findUniqueByProperty ( TSBaseUser.class, "userName", hisTask.getAssignee () );
                returnMap.put ( "assignee", tsUser );
                taskService.claim ( taskId, hisTask.getAssignee () );//先做个签收
            }
            List<Map> transList = activitiService.getOutTransitions ( taskId );
            String nextnode = "";
            if (transList != null && transList.size () > 0) {
                for (int i = 0; i < transList.size (); i++) {
                    if (i == transList.size () - 1) {
                        nextnode += transList.get ( i ).get ( "nextnode" ).toString ();
                    } else {
                        nextnode += transList.get ( i ).get ( "nextnode" ).toString () + ",";
                    }
                }
            }
            if (nextnode.contains ( "exclusiveGateway" )) {//如果是排他网关 传入参数
                Map<String, Object> variables = new HashMap<String, Object> ();
                variables.put ( "flag", approvalFlag );
                // 2 是驳回标记
                if ("2".equals ( approvalFlag )) {
                    //如果是驳回，默认指定最后一次操作的人
                    List<HistoricTaskInstance> hisTasks = historyService.createHistoricTaskInstanceQuery ().finished ().processInstanceId ( processInstanceId ).orderByHistoricTaskInstanceStartTime ().desc ().list ();
                    nextUser = hisTasks.get ( 0 ).getAssignee ();
                }
                variables.put ( expression, nextUser );
                taskService.complete ( taskId, variables );
            } else {
                boolean bflag = false;
                //流程变量参数
                Map<String, Object> map = new HashMap<String, Object> ();
                if (StringUtil.isNotEmpty ( approvalFlag )) {
                    map.put ( "flag", approvalFlag );
                }
                //判断如果下一步节点是会签节点的话，传入会签参数
                if (bflag) {
                    map.put ( WorkFlowGlobals.ASSIGNEE_USER_ID_LIST, nextUser );
                }
                if (!StringUtil.isNotEmpty ( model )) {
                    model = "1";
                }
                if ("1".equals ( model )) {
                    if ("end".equals ( nextnode )) {
                        taskJeecgService.endProcess ( taskId );
                    } else {
                        taskJeecgService.goProcessTaskNode ( taskId, nextnode, map );
                        String nextTskId = taskJeecgService.getTaskIdByProins ( processInstanceId, nextnode );
                        //如果下个节点不是会签节点，动态指派下一步处理人
                        if (!bflag) {
                            if (oConvertUtils.isNotEmpty ( nextUser )) {
                                if (nextUser.indexOf ( "," ) < 0) {
                                    //指定单个执行人
                                    taskService.setAssignee ( nextTskId, nextUser );
                                } else {
                                    //指定多人
                                    taskService.setAssignee ( nextTskId, "" );
                                    taskService.addCandidateUser ( nextTskId, nextUser );
                                }
                            }
                        }
                    }
                } else if ("2".equals ( model )) {
                    //多分支模式
                    taskService.complete ( taskId, map );
                }
            }
        } catch (Exception e) {
            e.printStackTrace ();
        }
        return returnMap;
    }

    public List<String> queryUserProcess(String id, String processDefinitionKey, boolean isPri, String appointTaskNodeDefinKey) {
        List<Task> taskList = new ArrayList<Task> ();
        if (isPri) {
            //只查询指定到当前人的代办
            if (StringUtil.isNotEmpty ( appointTaskNodeDefinKey )) {
                //如果需要根据taskNodeDefinationKey过滤
                List<Task> tasks = taskService.createTaskQuery ()
                        .taskAssignee ( id )
                        .taskDefinitionKey ( appointTaskNodeDefinKey )
                        .processDefinitionKeyLike ( processDefinitionKey ).list ();
                taskList.addAll ( tasks );
                List<Task> todoListtemp = taskService.createTaskQuery ()
                        .taskDefinitionKey ( appointTaskNodeDefinKey )
                        .taskCandidateUser ( id ).active ().processDefinitionKeyLike ( processDefinitionKey ).list ();
                taskList.addAll ( todoListtemp );
            } else {
                List<Task> tasks = taskService.createTaskQuery ().taskAssignee ( id ).processDefinitionKeyLike ( processDefinitionKey ).list ();
                taskList.addAll ( tasks );
                List<Task> todoListtemp = taskService.createTaskQuery ().taskCandidateUser ( id ).processDefinitionKeyLike ( processDefinitionKey ).active ().list ();
                taskList.addAll ( todoListtemp );
            }
        } else {
            //根据当前人所在的组查询
            if (StringUtil.isNotEmpty ( appointTaskNodeDefinKey )) {
                List<Task> tasks = taskService.createTaskQuery ().taskCandidateGroupIn ( Arrays.asList ( id.split ( "," ) ) )
                        .taskDefinitionKey ( appointTaskNodeDefinKey )
                        .processDefinitionKeyLike ( processDefinitionKey ).list ();
                taskList.addAll ( tasks );
            } else {
                List<Task> tasks = taskService.createTaskQuery ().taskCandidateGroupIn ( Arrays.asList ( id.split ( "," ) ) ).processDefinitionKeyLike ( processDefinitionKey ).list ();
                taskList.addAll ( tasks );
            }
        }
        List<HistoricTaskInstance> hisTaskIns = historyService.createHistoricTaskInstanceQuery ()
                .taskDefinitionKey ( appointTaskNodeDefinKey ).
                        taskAssignee ( id ).
                        processDefinitionKeyLike ( processDefinitionKey ).finished ().list ();

        List<String> busKeys = new ArrayList<String> ();
        for (HistoricTaskInstance historicTaskInstance : hisTaskIns) {
            String businessKey = "";
            HistoricProcessInstance hiproins = historyService.createHistoricProcessInstanceQuery ().processInstanceId ( historicTaskInstance.getProcessInstanceId () ).singleResult ();
            if (hiproins != null) {
                if (hiproins.getSuperProcessInstanceId () != null && hiproins.getBusinessKey () == null) {
                    hiproins = historyService.createHistoricProcessInstanceQuery ().processInstanceId ( hiproins.getSuperProcessInstanceId () ).singleResult ();
                    businessKey = hiproins.getBusinessKey ();
                } else {
                    businessKey = hiproins.getBusinessKey ();
                }
            }
            busKeys.add ( businessKey );
        }
        for (Task task : taskList) {
            String processInstanceId = task.getProcessInstanceId ();
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery ().processInstanceId ( processInstanceId ).singleResult ();
            busKeys.add ( processInstance.getBusinessKey () );//
        }

        return busKeys;
    }


    public List<Map<String, Object>> queryUserProcessReList(String id, String processDefinitionKey, boolean isPri, String appointTaskNodeDefinKey) {
        List<Task> taskList = new ArrayList<Task> ();
        if (isPri) {
            //只查询指定到当前人的代办
            if (StringUtil.isNotEmpty ( appointTaskNodeDefinKey )) {
                //如果需要根据taskNodeDefinationKey过滤
                List<Task> tasks = taskService.createTaskQuery ()
                        .taskAssignee ( id )
                        .taskDefinitionKey ( appointTaskNodeDefinKey )
                        .processDefinitionKeyLike ( processDefinitionKey ).list ();
                taskList.addAll ( tasks );
                List<Task> todoListtemp = taskService.createTaskQuery ()
                        .taskDefinitionKey ( appointTaskNodeDefinKey )
                        .taskCandidateUser ( id ).active ().processDefinitionKeyLike ( processDefinitionKey ).list ();
                taskList.addAll ( todoListtemp );
            } else {
                List<Task> tasks = taskService.createTaskQuery ().taskAssignee ( id ).processDefinitionKeyLike ( processDefinitionKey ).list ();
                taskList.addAll ( tasks );
                List<Task> todoListtemp = taskService.createTaskQuery ().taskCandidateUser ( id ).processDefinitionKeyLike ( processDefinitionKey ).active ().list ();
                taskList.addAll ( todoListtemp );
            }
        } else {
            //根据当前人所在的组查询
            if (StringUtil.isNotEmpty ( appointTaskNodeDefinKey )) {
                List<Task> tasks = taskService.createTaskQuery ().taskCandidateGroupIn ( Arrays.asList ( id.split ( "," ) ) )
                        .taskDefinitionKey ( appointTaskNodeDefinKey )
                        .processDefinitionKeyLike ( processDefinitionKey ).list ();
                taskList.addAll ( tasks );
            } else {
                List<Task> tasks = taskService.createTaskQuery ().taskCandidateGroupIn ( Arrays.asList ( id.split ( "," ) ) ).processDefinitionKeyLike ( processDefinitionKey ).list ();
                taskList.addAll ( tasks );
            }
        }
        List<HistoricTaskInstance> hisTaskIns = historyService.createHistoricTaskInstanceQuery ()
                .taskDefinitionKey ( appointTaskNodeDefinKey ).
                        taskAssignee ( id ).
                        processDefinitionKeyLike ( processDefinitionKey ).finished ().list ();

        List<Map<String, Object>> dataList = new ArrayList<Map<String, Object>> ();
        for (HistoricTaskInstance historicTaskInstance : hisTaskIns) {
            String businessKey = "";
            HistoricProcessInstance hiproins = historyService.createHistoricProcessInstanceQuery ().processInstanceId ( historicTaskInstance.getProcessInstanceId () ).singleResult ();
            if (hiproins != null) {
                if (hiproins.getSuperProcessInstanceId () != null && hiproins.getBusinessKey () == null) {
                    hiproins = historyService.createHistoricProcessInstanceQuery ().processInstanceId ( hiproins.getSuperProcessInstanceId () ).singleResult ();
                    businessKey = hiproins.getBusinessKey ();
                } else {
                    businessKey = hiproins.getBusinessKey ();
                }
            }

            Map<String, Object> map = new HashMap<String, Object> ();
            map.put ( "busId", businessKey );
            map.put ( "handleStatus", 2 );
            map.put ( "nodeName", historicTaskInstance.getName () );
            map.put ( "endTime", DataUtils.formatDate ( historicTaskInstance.getEndTime (), "yyyy-MM-dd HH:mm" ) );
            dataList.add ( map );
        }
        for (Task task : taskList) {
            String processInstanceId = task.getProcessInstanceId ();
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery ().processInstanceId ( processInstanceId ).singleResult ();
            Map<String, Object> map = new HashMap<String, Object> ();
            map.put ( "busId", processInstance.getBusinessKey () );
            map.put ( "handleStatus", 1 );
            map.put ( "id", task.getId () );
            map.put ( "instId", processInstanceId );
            map.put ( "nodeName", task.getName () );
            map.put ( "endTime", "" );
            dataList.add ( map );
        }

        return dataList;
    }


    public void endProcess(String planId) {
        try {
            Task task = taskService.createTaskQuery ().processInstanceBusinessKey ( planId ).active ().singleResult ();
            taskJeecgService.endProcess ( task.getId () );
        } catch (Exception e) {
            e.printStackTrace ();
        }
    }

    public String checkTaskHandle(String taskId) {
        try {
            ActHiTaskinst taskinst = systemService.get ( ActHiTaskinst.class, taskId );
            //已经被办理
            if (StringUtil.isNotEmpty ( taskinst.getDeleteReason () )) {
                return "n";
            }
            return "y";
        } catch (Exception e) {
            e.printStackTrace ();
            return "n";
        }
    }


}
